#include "x86_disassemble.h"
uint8_t prefix_code[12] = {0xf0, 0xf2, 0xf3, 0xf4,
                            0x2e, 0x36, 0x3e, 0x26, 0x64, 0x65,
                            0x66,
                            0x67,};

struct x86_instruction_t* susceptible_i_tables[0x100] = {};
int susceptible_count = 0x0;
bool put_state = true;

void x86_instruction_t_init(struct x86_instruction_t* x86_i_t)
{
    x86_i_t->prefix_count = 0x0;
    x86_i_t->vex_length = 0x0;
    x86_i_t->opcode_length = 0x0;
    x86_i_t->has_modrm = 0x0;
    x86_i_t->has_sib = 0x0;
    x86_i_t->displacement_size = 0x0;
    x86_i_t->immediate_size = 0x0;
}

void parse_prefix(struct x86_instruction_t* x86_i_t)
{
    uint8_t code;
    int32_t max_prefix_count = 4;
    while (x86_i_t->prefix_count < max_prefix_count) {
        code = *(x86_i_t->i_addr);
        // 检查当前字节是否是前缀
        bool is_prefix = false;
        int i = 0;
        for (; i < 12; i++) {
            if (code == prefix_code[i]) {
                x86_i_t->prefixes[x86_i_t->prefix_count++] = code;
                x86_i_t->i_addr++;
                is_prefix = true;
                break;
            }
        }
        // 如果当前字节不是前缀，停止解析
        if (!is_prefix) {
            break;
        }
    }
    // 打印前缀
    if (x86_i_t->prefix_count > 0) {
        if (put_state) put_str("prefix: ");
        int i = 0;
        for (; i < x86_i_t->prefix_count; i++) {
            if (put_state) put_int(x86_i_t->prefixes[i]);
        }
        if (put_state) put_str(" ");
    }

    // int counter = 0x0;
    // int prefix_counter;
    // while(1) {
    //     prefix_counter = x86_i_t->prefix_count;

    //     if (x86_i_t->prefix_count == 4) {
    //         break;
    //     }
    //     code  = *(x86_i_t->i_addr);
        
    //     for (;counter < 12; counter++) 
    //     {
    //         if (code == prefix_code[counter]) 
    //         {
    //             x86_i_t->prefixes[x86_i_t->prefix_count] = code;
    //             x86_i_t->prefix_count++;
    //             x86_i_t->i_addr++;
    //             continue;
    //         }
    //     }
    //     if (prefix_counter == x86_i_t->prefix_count) 
    //     {
    //         break;
    //     }
    // }
    // if (x86_i_t->prefix_count != 0x0) {
    //     counter = 0x0;
    //     if (put_state) put_str("prefix: ");
    //     for (;counter < x86_i_t->prefix_count;counter++) 
    //     {
    //         if (put_state) put_int(x86_i_t->prefixes[counter]);
    //     }
    //     if (put_state) put_str(" ");
    // }
}
void parse_opcode(struct x86_instruction_t* x86_i_t)
{
    int counter = 0x0;
    uint8_t code;
    int state = 0x0;
    while(1)
    {
        if (state)
        {
            break;
        }
        if (x86_i_t->opcode_length == 0x3)
        {
            break;
        }
        code  = *(x86_i_t->i_addr);
        x86_i_t->i_addr++;
        switch (code) {
            case PUSH_EAX:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_EAX;
            if (put_state) put_str("PUSH EAX ");
            break;
            case PUSH_EDX:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_EDX;
            if (put_state) put_str("PUSH EDX ");
            break;
            case PUSH_EBP:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_EBP;
            if (put_state) put_str("PUSH EBP ");
            break;
            case PUSH_ESI:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_ESI;
            if (put_state) put_str("PUSH ESI ");
            break;
            case PUSH_EDI:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_EDI;
            if (put_state) put_str("PUSH EDI ");
            break;
            case PUSH_EBX:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_EBX;
            if (put_state) put_str("PUSH EBX ");
            break;
            case PUSH_ECX:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_ECX;
            if (put_state) put_str("PUSH ECX ");
            break;
            case PUSH_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("PUSH ");
            break;
            case PUSHA_:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSHA_;
            if (put_state) put_str("PUSHA ");
            break;
            case PUSH_DS:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_DS;
            if (put_state) put_str("PUSH DS ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            susceptible_count++;
            break;
            case 0x06:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x06;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("CLTS ");
            } else {
                if (put_state) put_str("PUSH ES ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            }
            break;
            case 0xa0:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa0;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("PUSH FS ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            }else {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("MOV AL ");
            }
            break;
            case 0xa8:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa8;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("PUSH GS ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            }else {
                x86_i_t->immediate_size = 0x1;
                if (put_state) put_str("TEST AL ");
            }
            break;
            case PUSH_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSH_IMM32;
            x86_i_t->immediate_size = 0x4;
            if (put_state) put_str("PUSH ");
            break;



            case POP_EAX:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_EAX;
            if (put_state) put_str("POP EAX ");
            break;
            case POP_EDX:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_EDX;
            if (put_state) put_str("POP EDX ");
            break;
            case POP_EBX:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_EBX;
            if (put_state) put_str("POP EBX ");
            break;
            case POP_ESI:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_ESI;
            if (put_state) put_str("POP ESI ");
            break;
            case POP_EDI:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_EDI;
            if (put_state) put_str("POP EDI ");
            break;
            case POP_EBP:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_EBP;
            if (put_state) put_str("POP EBP ");
            break;
            case POP_ECX:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_ECX;
            if (put_state) put_str("POP ECX ");
            break;
            case POPA_:
            x86_i_t->opcode[x86_i_t->opcode_length] = POPA_;
            if (put_state) put_str("POPA ");
            break;
            case 0x8f:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x8f;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JG ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                    case 0x0:
                    if (put_state) put_str("POP ");
                    break;
                }
            }
            break;
            case POP_DS:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_DS;
            if (put_state) put_str("POP DS ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            susceptible_count++;
            break;
            case POP_ES:
            x86_i_t->opcode[x86_i_t->opcode_length] = POP_ES;
            if (put_state) put_str("POP ES ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            susceptible_count++;
            break;
            case 0xa9:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa9;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("POP GS ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            }else {
                x86_i_t->immediate_size = 0x4;
                if (put_state) put_str("TEST EAX ");
            }
            break;

            case MOV_M32_M32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_M32_M32;
            if (put_state) put_str("MOV M32 M32 ");
            break;
            case 0x89:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x89;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JNS ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("MOV ");
            }
            break;
            case 0xa1:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa1;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("POP FS ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            }else {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("MOV EAX ");
            }
            break;
            case 0xa3:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa3;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("BT ");
            } else {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("MOV EAX ");
            }
            break;
            case MOV_RM32_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_RM32_IMM32;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                if (x86_i_t->prefixes[0] == 0x66) 
                {
                    x86_i_t->immediate_size = 0x2;
                } else
                {
                    x86_i_t->immediate_size = 0x4;
                } 
            }
            if (put_state) put_str("MOV ");
            break;
            case MOV_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_R32_RM32;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
            }
            if (put_state) put_str("MOV ");
            break;
            case MOVZX_R32_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOVZX_R32_RM8;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
            }
            if (put_state) put_str("MOVZX ");
            break;
            case 0x88:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x88;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->immediate_size = 0x4;
                if (put_state) put_str("JS ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("MOV ");
            }
            break;
            case MOV_RM8_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_RM8_IMM8;
            {
                x86_i_t->immediate_size = 0x1;
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
            }
            if (put_state) put_str("MOV ");
            break;
            case MOV_EAX_IMM32_:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_EAX_IMM32_;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV EAX ");
            break;
            case MOV_EDX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_EDX_IMM32;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV EDX ");
            break;
            case MOV_ECX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_ECX_IMM32;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV ECX ");
            break;
            case MOV_EBX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_EBX_IMM32;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV EBX ");
            break;
            case 0xbe:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xbe;
            if (x86_i_t->opcode[0] == 0x0f) { //MOVSX_R32_RM8
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("MOVSX ");
            } else { //MOV_ESI_IMM32
                if (x86_i_t->prefixes[0] == 0x66) {
                    x86_i_t->immediate_size = 0x2;
                } else {
                    x86_i_t->immediate_size = 0x4;
                }
                if (put_state) put_str("MOV ESI ");
            }
            break;
            case MOV_EDI_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_EDI_IMM32;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV EDI ");
            break;
            case MOV_EBP_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_EBP_IMM32;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("MOV EBP ");
            break;
            case MOVZX_R32_RM16:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOVZX_R32_RM16;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
            }
            if (put_state) put_str("MOVZX ");
            break;
            case MOV_AL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_AL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("MOV AL ");
            break;
            case MOV_CL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_CL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("MOV CL ");
            break;
            case MOV_R8_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_R8_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("MOV ");
            break;
            case MOV_MOFFS8_AL:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_MOFFS8_AL;
            x86_i_t->displacement_size = 0x4;
            if (put_state) put_str("MOV AL ");
            break;
            case MOV_AH_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_AH_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("MOV AH ");
            break;



            case 0x83:// AND_RM32_IB  ADD_RM32_IMM8  CMP_RM32_IMM8
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x83;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JAE ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                x86_i_t->immediate_size = 0x1;
                switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                    case 0x0:
                    if (put_state) put_str("ADD ");
                    break;
                    case 0x1:
                    if (put_state) put_str("OR ");
                    break;
                    case 0x2:
                    if (put_state) put_str("ADC ");
                    break;
                    case 0x4:
                    if (put_state) put_str("AND ");
                    break;
                    case 0x5:
                    if (put_state) put_str("SUB ");
                    break;
                    case 0x6:
                    if (put_state) put_str("XOR ");
                    break;
                    case 0x7:
                    if (put_state) put_str("CMP ");
                    break;
                }
            }
            break;
            case ADD_EAX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = ADD_EAX_IMM32;
            {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("ADD EAX ");
            break;
            case 0x03:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x03;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("LSL ");
            } else {
                if (put_state) put_str("ADD ");
            }
            break;
            case ADD_R8_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = ADD_R8_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("ADD ");
            break;



            case 0x81:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x81;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            if (x86_i_t->prefixes[0] == 0x66) {
                x86_i_t->immediate_size = 0x2;
            } else {
                x86_i_t->immediate_size = 0x4;
            }
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0://ADD_RM32_IMM32
                if (put_state) put_str("ADD ");
                break;
                case 0x1:
                if (put_state) put_str("OR ");
                break;
                case 0x4:
                if (put_state) put_str("AND ");
                break;
                case 0x5://SUB_RM32_IMM32
                if (put_state) put_str("SUB ");
                break;
                case 0x7:
                if (put_state) put_str("CMP ");
                break;
            }
            break;

            case AND_EAX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = AND_EAX_IMM32;
            x86_i_t->immediate_size = 0X4;
            if (put_state) put_str("AND EAX ");
            break;
            case AND_AL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = AND_AL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("AND AL ");
            break;
            case AND_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = AND_RM32_R32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("AND ");
            break;
            case AND_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = AND_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("AND ");
            break;


            case DEC_EAX:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_EAX;
            if (put_state) put_str("DEC EAX ");
            break;
            case DEC_EBX:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_EBX;
            if (put_state) put_str("DEC EBX ");
            break;
            case DEC_EDI:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_EDI;
            if (put_state) put_str("DEC EDI ");
            break;
            case DEC_ECX:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_ECX;
            if (put_state) put_str("DEC ECX ");
            break;
            case DEC_EDX:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_EDX;
            if (put_state) put_str("DEC EDX ");
            break;
            case DEC_EBP:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_EBP;
            if (put_state) put_str("DEC EBP ");
            break;
            case DEC_ESI:
            x86_i_t->opcode[x86_i_t->opcode_length] = DEC_ESI;
            if (put_state) put_str("DEC ESI ");
            break;
            case 0xfe:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xfe;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0:
                if (put_state) put_str("INC ");
                break;
                case 0x1:
                if (put_state) put_str("DEC ");
                break;
            }
            break;

            case XOR_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = XOR_RM32_R32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("XOR ");
            break;
            case XOR_R8_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = XOR_R8_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("XOR ");
            break;
            case XOR_RM8_R8:
            x86_i_t->opcode[x86_i_t->opcode_length] = XOR_RM8_R8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("XOR ");
            break;
            case XOR_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = XOR_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("XOR ");
            break;

            case 0xf7:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xf7;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0:
                x86_i_t->immediate_size = 0x4;
                if (put_state) put_str("TEST ");
                break;
                case 0x2:
                if (put_state) put_str("NOT ");
                break;
                case 0x3:
                if (put_state) put_str("NEG ");
                break;
                case 0x5:
                if (put_state) put_str("IMUL ");
                case 0x6:
                if (put_state) put_str("DIV ");
                break;
            }
            break;

            case CLI:
            x86_i_t->opcode[x86_i_t->opcode_length] = CLI;
            if (put_state) put_str("CLI ");
            break;
            case STI:
            x86_i_t->opcode[x86_i_t->opcode_length] = STI;
            if (put_state) put_str("STI ");
            break;
            case CLD_:
            x86_i_t->opcode[x86_i_t->opcode_length] = CLD_;
            if (put_state) put_str("CLD ");
            break;


            case CALL_RE32:
            x86_i_t->opcode[x86_i_t->opcode_length] = CALL_RE32;
            {
                x86_i_t->displacement_size = 0x4;
            }
            if (put_state) put_str("CALL ");
            break;
            case 0XFF:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0XFF;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0:
                if (put_state) put_str("INCL ");
                break;
                case 0x1:
                if (put_state) put_str("DECL ");
                break;
                case 0x2:
                if (put_state) put_str("CALL ");
                break;
                case 0x5:
                if (put_state) put_str("LJMP ");
                break;
            }
            break;

            case CMP_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_RM32_R32;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
            }
            if (put_state) put_str("CMP ");
            break;
            case CMP_EAX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_EAX_IMM32;
            {
                x86_i_t->immediate_size = 0x4;
            }
            if (put_state) put_str("CMP EAX");
            break;
            case CMP_RM8_R8:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_RM8_R8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("CMP ");
            break;
            case CMP_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("CMP ");
            break;
            case CMP_AL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_AL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("CMP AL ");
            break;
            case CMP_R8_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMP_R8_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("CMP ");
            break;
            case CMPS_M8_M8:
            x86_i_t->opcode[x86_i_t->opcode_length] = CMPS_M8_M8;
            if (put_state) put_str("CMPS ");
            break;

            case 0x80:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x80;
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                x86_i_t->immediate_size = 0x1;
            }
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0:
                if (put_state) put_str("ADD ");
                break;
                case 0x1:
                if (put_state) put_str("OR ");
                break;
                case 0x4:
                if (put_state) put_str("AND ");
                break;
                case 0x6:
                if (put_state) put_str("XOR ");
                break;
                case 0x7:
                if (put_state) put_str("CMP ");
                break;
            }
            break;

            case 0xf6:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xf6;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            x86_i_t->immediate_size = 0x1;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x0:
                if (put_state) put_str("TESTB ");
                break;
                case 0x2:
                if (put_state) put_str("NOT ");
                break;
            }
            break;

            case JNE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JNE_REL8;
            {
                x86_i_t->displacement_size = 0x1;
            }
            if (put_state) put_str("JNE ");
            break;
            case 0x85: 
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x85;
            if (x86_i_t->opcode_length > 0) { // JNE_REL32
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JNE ");
            } else //TEST_RM32_R32
            {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("TEST ");
            }
            break;
            case JMP_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JMP_REL8;
            {
                x86_i_t->displacement_size = 0x1;
            }
            if (put_state) put_str("JMP ");
            break;
            case JMP_REL32:
            x86_i_t->opcode[x86_i_t->opcode_length] = JMP_REL32;
            {
                x86_i_t->displacement_size = 0x4;
            }
            if (put_state) put_str("JMP ");
            break;
            case JE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JE_REL8;
            {
                x86_i_t->displacement_size = 0x1;
            }
            if (put_state) put_str("JE ");
            break;
            case 0x84:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x84;
            if (x86_i_t->opcode_length > 0) 
            {
                x86_i_t->displacement_size = 0x4;//JE_REL32
                if (put_state) put_str("JE ");
            } else
            {
                x86_i_t->has_modrm = HAS_MODRM_T;//TEST_RM8_R8
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("TEST ");
            }
            break;
            case 0x8e:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x8e;
            if (x86_i_t->opcode[0] == 0x8e) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("MOV_SREG_RM16 ");
                susceptible_i_tables[susceptible_count] = x86_i_t;
                susceptible_count++;
            } else {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JLE ");
            }
            break;
            case JLE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JLE_REL8;
            {
                x86_i_t->displacement_size = 0x1;
            }
            if (put_state) put_str("JLE ");
            break;
            case JL_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JL_REL8;
            {
                x86_i_t->displacement_size = 0x1;
            }
            if (put_state) put_str("JL ");
            break;
            case JG_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JG_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JG ");
            break;
            case JBE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JBE_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JBE ");
            break;
            case JBE_REL32:
            x86_i_t->opcode[x86_i_t->opcode_length] = JBE_REL32;
            x86_i_t->displacement_size = 0x4;
            if (put_state) put_str("JBE ");
            break;
            case JB_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JB_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JB ");
            break;
            case JB_REL32:
            x86_i_t->opcode[x86_i_t->opcode_length] = JB_REL32;
            x86_i_t->displacement_size = 0x4;
            if (put_state) put_str("JB ");
            break;
            case JAE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JAE_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JAE ");
            break;
            case JA_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JA_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JAE ");
            break;
            case JGE_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JGE_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JGE ");
            break;
            case JS_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JS_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JS ");
            break;
            case JNS_REL8:
            x86_i_t->opcode[x86_i_t->opcode_length] = JNS_REL8;
            x86_i_t->displacement_size = 0x1;
            if (put_state) put_str("JNS ");
            break;


            case 0x8d:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x8d;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JGE ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("LEA ");
            }
            break;


            case 0xc1:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xc1;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            x86_i_t->immediate_size = 0x1;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x1:
                if (put_state) put_str("ROR ");
                break;
                case 0x4:
                if (put_state) put_str("SHL ");
                break;
                case 0x5:
                if (put_state) put_str("SHR ");
                break;
                case 0x7:
                if (put_state) put_str("SAR ");
                break;
            }
            break;
            case 0xa4:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xa4;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                x86_i_t->immediate_size = 0x1;
                if (put_state) put_str("SHLD ");
            } else {
                if (put_state) put_str("MOVSB ");
            }
            break;
            case 0xd1:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xd1;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x4:
                if (put_state) put_str("SHL ");
                break;
                case 0x7:
                if (put_state) put_str("SAR ");
                break;
            }
            break;
            case 0xd3:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xd3;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x4:
                if (put_state) put_str("SHL CL ");
                break;
                case 0x5:
                if (put_state) put_str("SHR CL ");
                break;
            }
            break;

            case OR_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_RM32_R32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("OR ");
            break;
            case OR_AL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_AL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("OR AL ");
            break;
            case OR_EAX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_EAX_IMM32;
            x86_i_t->immediate_size = 0x4;
            if (put_state) put_str("OR EAX ");
            break;
            case OR_R8_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_R8_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("OR ");
            break;
            case OR_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("OR ");
            break;
            case OR_RM8_R8:
            x86_i_t->opcode[x86_i_t->opcode_length] = OR_RM8_R8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("OR ");
            break;

            case 0x01:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x01;
            if (x86_i_t->opcode_length > 0) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                    case 0x2:
                    if (put_state) put_str("LGDT ");
                    break;
                    case 0x3:
                    if (put_state) put_str("LIDT ");
                    break;
                }
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("ADD ");
            }
            break;

            case SUB_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = SUB_RM32_R32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SUB ");
            break;
            case SUB_EAX_IMM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = SUB_EAX_IMM32;
            x86_i_t->immediate_size = 0x4;
            if (put_state) put_str("SUB EAX ");
            break;
            case SUB_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = SUB_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SUB ");
            break;
            case SUB_AL_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SUB_AL_IMM8;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("SUB AL ");
            break;
            case SUB_RM8_R8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SUB_RM8_R8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SUB ");
            break;


            case 0x0f:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x0f;
            break;
            case 0xdb:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xdb;
            break;
            case 0x9b:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x9b;
            break;
            case 0xdf:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xdf;
            break;



            case INC_EAX:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_EAX;
            if (put_state) put_str("INC EAX ");
            break;
            case INC_EBX:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_EBX;
            if (put_state) put_str("INC EBX ");
            break;
            case INC_ESI:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_ESI;
            if (put_state) put_str("INC ESI ");
            break;
            case INC_EDI:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_EDI;
            if (put_state) put_str("INC EDI ");
            break;
            case INC_ECX:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_ECX;
            if (put_state) put_str("INC ECX ");
            break;
            case INC_EDX:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_EDX;
            if (put_state) put_str("INC EDX ");
            break;
            case INC_EBP:
            x86_i_t->opcode[x86_i_t->opcode_length] = INC_EBP;
            if (put_state) put_str("INC EBP ");
            break;

            case IMUL_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = IMUL_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("IMUL ");
            break;
            case IMUL_R32_RM32_IMM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = IMUL_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("IMUL ");
            break;



            case 0x22:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x22;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_F;
                if (put_state) put_str("MOV CR3 ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("AND ");
            }
            
            break;
            case 0x20:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x20;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            if (x86_i_t->opcode[0] == 0x0f) {
                if (put_state) put_str("MOV CR3 ");
            } else {
                if (put_state) put_str("IMUL ");
            }
            break;
            case SETG_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETG_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETG ");
            break;
            case SETNE_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETNE_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETNE ");
            break;
            case SETE_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETE_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETE ");
            break;
            case 0xe2:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xe2;
            if (x86_i_t->opcode[0] == 0xdb) {
                if (put_state) put_str("FNCLEX ");
            } else {
                x86_i_t->displacement_size = 0x1;
                if (put_state) put_str("LOOP ");
            }
            break;
            case 0x90:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x90;
            if (x86_i_t->opcode_length > 0) {
                if (put_state) put_str("XCHG ");
            } else {
                if (put_state) put_str("NOP ");
            }
            break;
            case 0x87:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x87;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->displacement_size = 0x4;
                if (put_state) put_str("JG ");
            } else {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("XCHG ");
            }
            break;
            break;
            case LEAVE:
            x86_i_t->opcode[x86_i_t->opcode_length] = LEAVE;
            if (put_state) put_str("LEAVE ");
            break;
            case RET:
            x86_i_t->opcode[x86_i_t->opcode_length] = RET;
            if (put_state) put_str("RET ");
            break;
            case RET_IMM16:
            x86_i_t->opcode[x86_i_t->opcode_length] = RET_IMM16;
            x86_i_t->immediate_size = 0x2;
            if (put_state) put_str("RET ");
            break;
            case IRET_:
            x86_i_t->opcode[x86_i_t->opcode_length] = IRET_;
            if (put_state) put_str("IRET ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            *((uint8_t*)susceptible_i_tables[susceptible_count]->start_i) = CLI;
            susceptible_count++;
            break;
            case OUT_DX_AL:
            x86_i_t->opcode[x86_i_t->opcode_length] = OUT_DX_AL;
            if (put_state) put_str("OUT_DX_AL ");
            break;
            case OUT_IMM8_AL:
            x86_i_t->opcode[x86_i_t->opcode_length] = OUT_IMM8_AL;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("OUT_IMM8_AL ");
            break;
            case OUTS_DX_M32:
            x86_i_t->opcode[x86_i_t->opcode_length] = OUTS_DX_M32;
            if (put_state) put_str("OUTS DX M32 ");
            break;
            case IN_AL_DX:
            x86_i_t->opcode[x86_i_t->opcode_length] = IN_AL_DX;
            if (put_state) put_str("IN_AL_DX ");
            break;
            case INSW_M32_DX:
            x86_i_t->opcode[x86_i_t->opcode_length] = INSW_M32_DX;
            if (put_state) put_str("INSW M32 DX ");
            break;
            case 0xab:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xab;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("BTS ");
            } else {
                if (put_state) put_str("STOSD ");
            }
            break;
            case STOS_:
            x86_i_t->opcode[x86_i_t->opcode_length] = STOS_;
            if (put_state) put_str("STOS ");
            break;
            case SETAE_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETAE_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETAE ");
            break;
            case PUSHF_:
            x86_i_t->opcode[x86_i_t->opcode_length] = PUSHF_;
            if (put_state) put_str("PUSHF ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            *((uint8_t*)susceptible_i_tables[susceptible_count]->start_i) = CLI;
            susceptible_count++;
            break;
            case POPF_:
            x86_i_t->opcode[x86_i_t->opcode_length] = POPF_;
            if (put_state) put_str("POPF ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            susceptible_count++;
            break;
            case MOV_RM16_SREG:
            x86_i_t->opcode[x86_i_t->opcode_length] = MOV_RM16_SREG;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("MOV_RM16_SREG ");
            susceptible_i_tables[susceptible_count] = x86_i_t;
            susceptible_count++;
            break;
            case LSS_R32_M16_32:
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->opcode[x86_i_t->opcode_length] = LSS_R32_M16_32;
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("LSS ");
            } else {
                x86_i_t->immediate_size = 0x1;
                if (put_state) put_str("MOV DL ");
            }
            break;
            case FNINIT_:
            if (x86_i_t->opcode[x86_i_t->opcode_length - 1] == 0xdb) {
                x86_i_t->opcode[x86_i_t->opcode_length] = FNINIT_;
                if (put_state) put_str("FNINIT ");
            }
            break;
            case FSTSW_AX_:
            if (x86_i_t->opcode[x86_i_t->opcode_length - 1] == 0xdf) {
                x86_i_t->opcode[x86_i_t->opcode_length] = FSTSW_AX_;
                if (put_state) put_str("FSTSW_AX ");
            }
            break;
            case FNSETPM_:
            if (x86_i_t->opcode[x86_i_t->opcode_length - 1] == 0xdb) {
                x86_i_t->opcode[x86_i_t->opcode_length] = FNSETPM_;
                if (put_state) put_str("FNSETPM ");
            }
            break;
            case 0xdd:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xdd;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_F;
            switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                case 0x4:
                if (put_state) put_str("FRSTOR ");
                break;
                case 0x6:
                if (put_state) put_str("FNSAVE ");
                break;
            }
            break;

            case OUTSB_:
            x86_i_t->opcode[x86_i_t->opcode_length] = OUTSB_;
            if (put_state) put_str("OUTSB_ESI_DX");
            break;
            case STD_:
            x86_i_t->opcode[x86_i_t->opcode_length] = STD_;
            if (put_state) put_str("STD ");
            break;
            case INT_:
            x86_i_t->opcode[x86_i_t->opcode_length] = INT_;
            x86_i_t->immediate_size = 0x1;
            if (put_state) put_str("INT ");
            break;
            case 0x00:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0x00;
            x86_i_t->has_modrm = HAS_MODRM_T;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->modrm_r = MODRM_R_F;
                switch (((*(x86_i_t->i_addr)) >> 3) & 0x07) {
                    case 0x1:
                    if (put_state) put_str("STR ");
                    break;
                    case 0x2:
                    if (put_state) put_str("LLDT ");
                    break;
                    case 0x3:
                    if (put_state) put_str("LTR ");
                    break;
                }
            } else {
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("ADD ");
            }
            break;
            case BSF_R32_RM32:
            x86_i_t->opcode[x86_i_t->opcode_length] = BSF_R32_RM32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("BSF ");
            break;
            case 0xb3:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xb3;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                if (put_state) put_str("BTR ");
            } else {
                x86_i_t->immediate_size = 0x1;
                if (put_state) put_str("MOV BL ");
            }
            break;
            case SBB_RM32_R32:
            x86_i_t->opcode[x86_i_t->opcode_length] = SBB_RM32_R32;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SBB ");
            break;
            case SCAS_AL_ES_EDI:
            x86_i_t->opcode[x86_i_t->opcode_length] = SCAS_AL_ES_EDI;
            if (put_state) put_str("SCAS AL ES:EDI ");
            break;
            case SETB_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETB_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETB ");
            break;
            case 0xac:
            x86_i_t->opcode[x86_i_t->opcode_length] = 0xac;
            if (x86_i_t->opcode[0] == 0x0f) {
                x86_i_t->has_modrm = HAS_MODRM_T;
                x86_i_t->modrm_r = MODRM_R_T;
                x86_i_t->immediate_size = 0x1;
                if (put_state) put_str("SHRD ");
            } else {
                if (put_state) put_str("LODS ");
            }
            break;
            case LODS_M23:
            x86_i_t->opcode[x86_i_t->opcode_length] = LODS_M23;
            if (put_state) put_str("LODS ");
            break;
            case SETBE_RM8:
            x86_i_t->opcode[x86_i_t->opcode_length] = SETBE_RM8;
            x86_i_t->has_modrm = HAS_MODRM_T;
            x86_i_t->modrm_r = MODRM_R_T;
            if (put_state) put_str("SETBE ");
            break;

            default:
            if (put_state) put_int(x86_i_t->i_addr);
            if (put_state) put_str("  ");
            if (put_state) put_int(code);
            if (put_state) put_str(" NO_OPCODE ");

            asm("jmp .");
        }
        x86_i_t->opcode_length++;
        if (code != 0x0f && code != 0xdb && code != 0x9b && code != 0xdf) {
            state = 0x1;
        } else {
            if (code == 0x9b && x86_i_t->opcode_length == 1) {
                state = 0x1;
            } else {
                state = 0x0;
            }
            
        }
    }
    counter = 0x0;
    if (put_state) put_str("opcode:");
    for (;counter < x86_i_t->opcode_length;counter++) 
    {
        if (put_state) put_int(x86_i_t->opcode[counter]);
    }
    if (put_state) put_str(" ");


}
void parse_modrm(struct x86_instruction_t* x86_i_t)
{
    if (!(x86_i_t->has_modrm)) 
    {
        return;
    }

    x86_i_t->modrm = *(x86_i_t->i_addr);
    x86_i_t->i_addr++;
    uint8_t mod = (x86_i_t->modrm >> 6) & 0x03;  // 高 2 位
    uint8_t reg = (x86_i_t->modrm >> 3) & 0x07;  // 中间 3 位
    uint8_t rm  = x86_i_t->modrm & 0x07;         // 低 3 位

    if (put_state) put_str("modrm:");
    if (put_state) put_int(x86_i_t->modrm);
    if (put_state) put_str(" ");
    if (x86_i_t->modrm_r) {
        if (x86_i_t->opcode[0] == 0x8e) {
            switch (reg) {
                case 0:
                if (put_state) put_str("ES ");
                break;
                case 1:
                if (put_state) put_str("CS ");
                break;
                case 2:
                if (put_state) put_str("SS ");
                break;
                case 3:
                if (put_state) put_str("DS ");
                break;
                case 4:
                if (put_state) put_str("FS ");
                break;
                case 5:
                if (put_state) put_str("GS ");
                break;
                case 6:
                asm("jmp .");
                break;
                case 7:
                asm("jmp .");
                break;
            }
        } else {
            switch (reg) {
                case 0:
                if (put_state) put_str("EAX ");
                break;
                case 1:
                if (put_state) put_str("ECX ");
                break;
                case 2:
                if (put_state) put_str("EDX ");
                break;
                case 3:
                if (put_state) put_str("EBX ");
                break;
                case 4:
                if (put_state) put_str("ESP ");
                break;
                case 5:
                if (put_state) put_str("EBP ");
                break;
                case 6:
                if (put_state) put_str("ESI ");
                break;
                case 7:
                if (put_state) put_str("EDI ");
                break;
            }
        }
        
    }
    switch (mod) {
        case 0x0:
        switch (rm) {
            case 0x0:
            if (put_state) put_str("[EAX]");
            break;
            case 0x1:
            if (put_state) put_str("[ECX]");
            break;
            case 0x2:
            if (put_state) put_str("[EDX]");
            break;
            case 0x3:
            if (put_state) put_str("[EBX]");
            break;
            case 0x4:
            {
                x86_i_t->has_sib = 0x1;
            }
            break;
            case 0x5:
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x6:
            if (put_state) put_str("[ESI]");
            break;
            case 0x7:
            if (put_state) put_str("[EDI]");
            break;
        }
        break;

        case 0x1:
        switch (rm) {
            case 0x0:
            if (put_state) put_str("[EAX + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x1:
            if (put_state) put_str("[ECX + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x2:
            if (put_state) put_str("[EDX + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x3:
            if (put_state) put_str("[EBX + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x4:
            {
                x86_i_t->displacement_size = 0x1;
                x86_i_t->has_sib = 0x1;
            }
            break;
            case 0x5:
            if (put_state) put_str("[EBP + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x6:
            if (put_state) put_str("[ESI + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
            case 0x7:
            if (put_state) put_str("[EDI + disp8]");
            {
                x86_i_t->displacement_size = 0x1;
            }
            break;
        }
        break;
        case 0x2:
        switch (rm) {
            case 0x0:
            if (put_state) put_str("[EAX + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x1:
            if (put_state) put_str("[ECX + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x2:
            if (put_state) put_str("[EDX + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x3:
            if (put_state) put_str("[EBX + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x4:
            {
                x86_i_t->displacement_size = 0x4;
                x86_i_t->has_sib = 0x1;
            }
            break;
            case 0x5:
            if (put_state) put_str("[EBP + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x6:
            if (put_state) put_str("[ESI + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
            case 0x7:
            if (put_state) put_str("[EDI + disp32]");
            {
                x86_i_t->displacement_size = 0x4;
            }
            break;
        }
        break;
        case 0x3:
        switch (rm) {
            case 0x0:
            if (put_state) put_str("EAX");
            break;
            case 0x1:
            if (put_state) put_str("ECX");
            break;
            case 0x2:
            if (put_state) put_str("EDX");
            break;
            case 0x3:
            if (put_state) put_str("EBX");
            break;
            case 0x4:
            if (put_state) put_str("ESP");
            break;
            case 0x5:
            if (put_state) put_str("EBP");
            break;
            case 0x6:
            if (put_state) put_str("ESI");
            break;
            case 0x7:
            if (put_state) put_str("EDI");
            break;
        }
        break;
        default:
        asm("jmp .");
    }
    if (put_state) put_str(" ");

}
void parse_sib(struct x86_instruction_t* x86_i_t)
{
    if (!(x86_i_t->has_sib))
    {
        return;
    }
    x86_i_t->sib = *(x86_i_t->i_addr);
    x86_i_t->i_addr++;
    uint8_t scale = (x86_i_t->sib >> 6) & 0x03;  // 高 2 位
    uint8_t index = (x86_i_t->sib >> 3) & 0x07;  // 中间 3 位
    uint8_t base  = x86_i_t->sib & 0x07;         // 低 3 位

    if (put_state) put_str("sib:");
    if (put_state) put_int(x86_i_t->sib);
    if (put_state) put_str(" ");

    if (put_state) put_str("s:");
    switch (scale) {
        case 0x0:
        if (put_state) put_str("0");
        break;
        case 0x1:
        if (put_state) put_str("1");
        break;
        case 0x2:
        if (put_state) put_str("2");
        break;
        case 0x3:
        if (put_state) put_str("8");
        break;

    }
    if (put_state) put_str(" ");

    if (put_state) put_str("i:");
    switch (index) {
        case 0:
        if (put_state) put_str("EAX");
        break;
        case 1:
        if (put_state) put_str("ECX");
        break;
        case 2:
        if (put_state) put_str("EDX");
        break;
        case 3:
        if (put_state) put_str("EBX");
        break;
        case 4:
        if (put_state) put_str("0");
        break;
        case 5:
        if (put_state) put_str("EBP");
        break;
        case 6:
        if (put_state) put_str("ESI");
        break;
        case 7:
        if (put_state) put_str("EDI");
        break;
    }
    if (put_state) put_str(" ");

    if (put_state) put_str("b:");
    switch (base) {
        case 0:
        if (put_state) put_str("EAX");
        break;
        case 1:
        if (put_state) put_str("ECX");
        break;
        case 2:
        if (put_state) put_str("EDX");
        break;
        case 3:
        if (put_state) put_str("EBX");
        break;
        case 4:
        if (put_state) put_str("ESP");
        break;
        case 5:
        if (((x86_i_t->modrm >> 6) & 0x03) == 0x0) {
            if (put_state) put_str("0");
            x86_i_t->displacement_size = 0x4;
        } else {
            if (put_state) put_str("EBP");
        }
        break;
        case 6:
        if (put_state) put_str("ESI");
        break;
        case 7:
        if (put_state) put_str("EDI");
        break;
    }
    if (put_state) put_str(" ");


}
void parse_displacement(struct x86_instruction_t* x86_i_t)
{
    if (!(x86_i_t->displacement_size))
    {
        return;
    }
    switch(x86_i_t->displacement_size) {
        case 0x1:
        x86_i_t->displacement = *(x86_i_t->i_addr);
        x86_i_t->i_addr++;
        if (put_state) put_str("disp8:");
        if (put_state) put_int(x86_i_t->displacement);
        break;
        case 0x2:
        x86_i_t->displacement = *((uint16_t*)(x86_i_t->i_addr));
        x86_i_t->i_addr += 2;
        if (put_state) put_str("disp16:");
        if (put_state) put_int(x86_i_t->displacement);
        break;
        case 0x4:
        x86_i_t->displacement = *((int*)(x86_i_t->i_addr));
        x86_i_t->i_addr += 4;
        if (put_state) put_str("disp32:");
        if (put_state) put_int(x86_i_t->displacement);
        break;
        default:
        asm("jmp .");
    }
    if (put_state) put_str(" ");
    

}
void parse_immediate(struct x86_instruction_t* x86_i_t){
    if (!(x86_i_t->immediate_size))
    {
        return;
    }
    switch (x86_i_t->immediate_size) {
        case 0x1:
        x86_i_t->immediate = *(x86_i_t->i_addr);
        x86_i_t->i_addr++;
        if (put_state) put_str("imm8:");
        if (put_state) put_int(x86_i_t->immediate);
        break;
        case 0x2:
        x86_i_t->immediate = *((uint16_t*)(x86_i_t->i_addr));
        x86_i_t->i_addr += 2;
        if (put_state) put_str("imm16:");
        if (put_state) put_int(x86_i_t->immediate);
        break;
        case 0x4:
        x86_i_t->immediate = *((uint32_t*)(x86_i_t->i_addr));
        x86_i_t->i_addr += 4;
        if (put_state) put_str("imm32:");
        if (put_state) put_int(x86_i_t->immediate);
        break;
        default:
        asm("jmp .");
    }
    
}

void x86_dis(struct x86_instruction_t* x86_i_t) {
    x86_instruction_t_init(x86_i_t);
    parse_prefix(x86_i_t);
    parse_opcode(x86_i_t);
    parse_modrm(x86_i_t);
    parse_sib(x86_i_t);
    parse_displacement(x86_i_t);
    parse_immediate(x86_i_t);
}
void x86_disassemble(void* i_addr, void* d_addr) {
    struct x86_instruction_t* x86_it_table = get_kernel_pages(400);
    while(1) 
    {
        // if ((uint32_t)i_addr == 0xc05000a9) {
        //     i_addr = 0xc0505400;
        // } else if ((uint32_t)i_addr == 0xc0505414) {
        //     i_addr = 0xc0505428;
        // } else if ((uint32_t)i_addr == 0xc05054a6) {
        //     i_addr = 0xc05064b8;
        // } else if ((uint32_t)i_addr == 0xc05173fb) {
        //     i_addr = 0xc05173fe;
        // } else if ((uint32_t)i_addr == 0xc05175a4) {
        //     i_addr = 0xc05175be;
        // } else if ((uint32_t)i_addr == 0xc05175ef) {
        //     i_addr = 0xc0517742;
        // } else if ((uint32_t)i_addr == 0xc05177c0) {
        //     i_addr = 0xc0517bc0;
        // } else if ((uint32_t)i_addr == 0xc0517d2f) {
        //     i_addr = 0xc0517d40;
        // }  linux0.11
        x86_it_table->i_addr = i_addr;
        x86_it_table->start_i = i_addr;
        
        x86_instruction_t_init(x86_it_table);
        parse_prefix(x86_it_table);
        parse_opcode(x86_it_table);
        parse_modrm(x86_it_table);
        parse_sib(x86_it_table);
        parse_displacement(x86_it_table);
        parse_immediate(x86_it_table);
        if (put_state) put_str("\n");
        i_addr = x86_it_table->i_addr;
        if (i_addr == d_addr) {
            break;
        }
        x86_it_table++;
        
        
    }
    if (put_state) put_str("ok   ");
    if (put_state) put_int(i_addr);
    if (put_state) put_str("\n");
    int count = 0x0;
    while(count < susceptible_count) {
        *((uint8_t*)susceptible_i_tables[count]->start_i) = CLI;
        if (put_state) put_int(susceptible_i_tables[count]->start_i);
        if (put_state) put_str("\n");
        count++;
    }
}